﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Data;
using Prodma.DataAccess.Database;
using Prodma.DataAccess.Interfaces.Models;
using Prodma.DataAccess.Models.ViewModels;
using Prodma.DataAccess.Repositories;
using Prodma.DataAccess.Helper.Enumerators;
using System.Configuration;

namespace Prodma.DataAccess.DataService
{
    public class CategoryService : ICategoryRepository
    {

        private DataContext context = new DataContext();


        #region ICategoryRepository Members

        public IList<int> GetSectionList()
        {
            DataContext context = new DataContext();
            using (context)
            {
                var list = (from category in context.tb_Category
                            group category by category.tb_Section.Id into section
                            select section.Key).ToList();

                return list;
            }
        }
        #endregion

        #region IRecordOperation<tb_Category,CategoryVm> Members

        public IList<CategoryVm> GetList()
        {
            throw new NotImplementedException();
        }

        public void New(tb_Category entity)
        {
            DataContext context = new DataContext();
            using (context)
            {
                context.AddTotb_Category(entity);
                context.SaveChanges();
            }
        }
        public CategoryVm Edit(int id)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var edit = (from category in context.tb_Category
                            where category.Id == id
                            select new CategoryVm()
                            {
                                Id = category.Id,
                                Name = category.Name,
                                Title = category.Title,
                                ShowContentCount = category.ShowContentCount,
                                ShowOnFront = category.ShowOnFront,
                                ShowInArchive = category.ShowInArchive,
                                Style = category.Style,
                                Section = new SectionVm() { Id = category.tb_Section.Id, Name = category.tb_Section.Name },
                                State = new StateVm() { Id = category.tb_State.Id, Name = category.tb_State.Name }
                            }).FirstOrDefault();

                return edit;
            }
        }
        public void Update(int id, tb_Category entity)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var edit = (from category in context.tb_Category
                            where category.Id == id
                            select category).FirstOrDefault();

                edit.Name = entity.Name;
                edit.Title = entity.Title;
                edit.ShowContentCount = entity.ShowContentCount;
                edit.ShowOnFront = entity.ShowOnFront;
                edit.ShowInArchive = entity.ShowInArchive;
                edit.Style = entity.Style;
                edit.tb_SectionReference.EntityKey = entity.tb_SectionReference.EntityKey;
                edit.tb_StateReference.EntityKey = entity.tb_StateReference.EntityKey;

                context.SaveChanges();
            }
        }
        public void Delete(int id)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var delete = (from category in context.tb_Category
                              where category.Id == id
                              select category).FirstOrDefault();

                context.DeleteObject(delete);
                context.SaveChanges();
            }
        }
        #endregion

        #region IPageOperation<CategoryVm> Members

        public IList<CategoryVm> GetList(int page)
        {
            int limitValue = Convert.ToInt32(ConfigurationManager.AppSettings["dataPagerLimit"]);
            int skipValue = page * limitValue;
            DataContext context = new DataContext();
            using (context)
            {
                var list = (from category in context.tb_Category
                            join order in context.tb_CategoryOrder
                                on category.Id equals order.Category
                            select new CategoryVm()
                            {
                                Id = category.Id,
                                Name = category.Name,
                                Title = category.Title,
                                Style = category.Style,
                                Order = new CategoryOrderVm() { OrderNo = order.OrderNo },
                                Section = new SectionVm() { Id = category.tb_Section.Id, Name = category.tb_Section.Name },
                                ShowOnFront = category.ShowOnFront,
                                ShowInArchive = category.ShowInArchive,
                                State = new StateVm() { Id = category.tb_State.Id, Name = category.tb_State.Name }
                            }).OrderByDescending(x => x.Order.OrderNo).Skip(skipValue).Take(limitValue).ToList();

                return list;
            }
        }
        public int GetTotalRowCount()
        {
            DataContext context = new DataContext();
            using (context)
            {
                int rowCount = (from category in context.tb_Category
                                select category).Count();

                return rowCount;
            }
        }
        #endregion

        #region IPageableFindOperation<CategoryVm> Members

        public IList<CategoryVm> GetList(int page, Dictionary<string, string> find)
        {
            int limitValue = Convert.ToInt32(ConfigurationManager.AppSettings["dataPagerLimit"]);
            int skipValue = page * limitValue;

            string findName = find["name"];
            DataContext context = new DataContext();
            using (context)
            {
                var list = (from category in context.tb_Category
                            join order in context.tb_CategoryOrder
                                on category.Id equals order.Category
                            where category.Name.StartsWith(findName)
                            select new CategoryVm()
                            {
                                Id = category.Id,
                                Name = category.Name,
                                Title = category.Title,
                                Style = category.Style,
                                Order = new CategoryOrderVm() { OrderNo = order.OrderNo },
                                Section = new SectionVm() { Id = category.tb_Section.Id, Name = category.tb_Section.Name },
                                ShowOnFront = category.ShowOnFront,
                                ShowInArchive = category.ShowInArchive,
                                State = new StateVm() { Id = category.tb_State.Id, Name = category.tb_State.Name }
                            }).OrderByDescending(x => x.Order.OrderNo).Skip(skipValue).Take(limitValue).ToList();

                return list;
            }
        }
        public int GetTotalRowCount(Dictionary<string, string> find)
        {
            string findName = find["name"];
            DataContext context = new DataContext();
            using (context)
            {
                int rowCount = (from category in context.tb_Category
                                where category.Name.StartsWith(findName)
                                select category).Count();

                return rowCount;
            }
        }
        #endregion

        #region IParentRelationshipOperation Members

        public IList<int> GetCounts()
        {
            DataContext context = new DataContext();
            using (context)
            {
                var countList = (from category in context.tb_Category
                                 group category by category.tb_Section.Id into section
                                 select section.Count()).ToList();

                return countList;
            }
        }
        public IList<int> GetCounts(string find)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var countList = (from category in context.tb_Category
                                 where category.Name.StartsWith(find)
                                 group category by category.tb_Section.Id into section
                                 select section.Count()).ToList();

                return countList;
            }
        }
        #endregion

        #region IOrderOperation<CategoryOrderVm> Members

        public void OrderUp(int id, CategoryOrderVm viewModel)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var currentOrder = (from order in context.tb_CategoryOrder
                                    where order.Category == viewModel.Category &&
                                          order.tb_Section.Id == viewModel.Section &&
                                          order.OrderNo == viewModel.OrderNo
                                    select order).FirstOrDefault();

                var nextOrder = (from order in context.tb_CategoryOrder
                                 where order.OrderNo > viewModel.OrderNo &&
                                       order.tb_Section.Id == viewModel.Section
                                 select order).OrderBy(x => x.OrderNo).FirstOrDefault();

                if (nextOrder != null)
                {
                    nextOrder.OrderNo--;
                    currentOrder.OrderNo++;
                }

                context.SaveChanges();
            }
        }
        public void OrderDown(int id, CategoryOrderVm viewModel)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var currentOrder = (from order in context.tb_CategoryOrder
                                    where order.Category == viewModel.Category &&
                                          order.tb_Section.Id == viewModel.Section &&
                                          order.OrderNo == viewModel.OrderNo
                                    select order).FirstOrDefault();

                var previousOrder = (from order in context.tb_CategoryOrder
                                     where order.OrderNo < viewModel.OrderNo &&
                                           order.tb_Section.Id == viewModel.Section
                                     select order).OrderByDescending(x => x.OrderNo).FirstOrDefault();

                if (previousOrder != null)
                {
                    previousOrder.OrderNo++;
                    currentOrder.OrderNo--;
                }

                context.SaveChanges();
            }
        }
        public void SetOrder(int id, CategoryOrderVm viewModel)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var lastOrder = (from order in context.tb_CategoryOrder
                                 where order.tb_Section.Id == viewModel.Section
                                 select order).OrderByDescending(x => x.OrderNo).Take(1).FirstOrDefault();

                if (viewModel.SetOrderNo > lastOrder.OrderNo || viewModel.SetOrderNo <= 0)
                {
                    return;
                }

                var currentOrder = (from order in context.tb_CategoryOrder
                                    where order.Category == viewModel.Category &&
                                          order.tb_Section.Id == viewModel.Section &&
                                          order.OrderNo == viewModel.OrderNo
                                    select order).FirstOrDefault();

                int setOrderNo = (lastOrder.OrderNo - viewModel.SetOrderNo) + 1;
                int fark = setOrderNo - currentOrder.OrderNo;
                int oldCurrentOrder = currentOrder.OrderNo;
                currentOrder.OrderNo = setOrderNo;

                if (fark > 0)
                {
                    var nextOrder = (from order in context.tb_CategoryOrder
                                     where order.OrderNo > oldCurrentOrder &&
                                           order.OrderNo <= setOrderNo &&
                                           order.tb_Section.Id == viewModel.Section
                                     select order).OrderBy(x => x.OrderNo).ToList();

                    foreach (tb_CategoryOrder m in nextOrder)
                    {
                        m.OrderNo--;
                        context.SaveChanges();
                    }
                }
                else if (fark <= 0)
                {
                    var previousOrder = (from order in context.tb_CategoryOrder
                                         where order.OrderNo < oldCurrentOrder &&
                                               order.OrderNo >= setOrderNo &&
                                               order.tb_Section.Id == viewModel.Section
                                         select order).OrderBy(x => x.OrderNo).ToList();

                    foreach (tb_CategoryOrder m in previousOrder)
                    {
                        m.OrderNo++;
                        context.SaveChanges();
                    }
                }

                context.SaveChanges();
            }
        }
        #endregion

        #region IStateOperation Members

        public void SetActive(int id)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var viewState = (from category in context.tb_Category
                                 where category.Id == id
                                 select category).FirstOrDefault();

                viewState.tb_StateReference.EntityKey = new EntityKey("DataContext.tb_State", "Id", Convert.ToInt32(State.Active));

                context.SaveChanges();
            }
        }
        public void SetPassive(int id)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var viewState = (from category in context.tb_Category
                                 where category.Id == id
                                 select category).FirstOrDefault();

                viewState.tb_StateReference.EntityKey = new EntityKey("DataContext.tb_State", "Id", Convert.ToInt32(State.Passive));

                context.SaveChanges();
            }
            }
        #endregion

    }
}
